home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / share / pygtk / 2.0 / codegen / docgen.py < prev    next >
Text File  |  2006-01-20  |  32KB  |  752 lines

  1. #!/usr/bin/env python
  2. # -*- Mode: Python; py-indent-offset: 4 -*-
  3. import sys, os, string, re, getopt
  4.  
  5. import defsparser
  6. import definitions
  7. import override
  8. import docextract
  9.  
  10. class Node:
  11.     def __init__(self, name, interfaces=[]):
  12.         self.name = name
  13.         self.interfaces = interfaces
  14.         self.subclasses = []
  15.     def add_child(self, node):
  16.         self.subclasses.append(node)
  17.  
  18. def build_object_tree(parser):
  19.     # reorder objects so that parent classes come first ...
  20.     objects = parser.objects[:]
  21.     pos = 0
  22.     while pos < len(objects):
  23.         parent = objects[pos].parent
  24.         for i in range(pos+1, len(objects)):
  25.             if objects[i].c_name == parent:
  26.                 objects.insert(i+1, objects[pos])
  27.                 del objects[pos]
  28.                 break
  29.         else:
  30.             pos = pos + 1
  31.  
  32.     root = Node(None)
  33.     nodes = { None: root }
  34.     for obj_def in objects:
  35.         parent_node = nodes[obj_def.parent]
  36.         node = Node(obj_def.c_name, obj_def.implements)
  37.         parent_node.add_child(node)
  38.         nodes[node.name] = node
  39.  
  40.     if parser.interfaces:
  41.         interfaces = Node('gobject.GInterface')
  42.         root.add_child(interfaces)
  43.         nodes[interfaces.name] = interfaces
  44.         for obj_def in parser.interfaces:
  45.             node = Node(obj_def.c_name)
  46.             interfaces.add_child(node)
  47.             nodes[node.name] = node
  48.  
  49.     if parser.boxes:
  50.         boxed = Node('gobject.GBoxed')
  51.         root.add_child(boxed)
  52.         nodes[boxed.name] = boxed
  53.         for obj_def in parser.boxes:
  54.             node = Node(obj_def.c_name)
  55.             boxed.add_child(node)
  56.             nodes[node.name] = node
  57.  
  58.     if parser.pointers:
  59.         pointers = Node('gobject.GPointer')
  60.         root.add_child(pointers)
  61.         nodes[pointers.name] = pointers
  62.         for obj_def in parser.pointers:
  63.             node = Node(obj_def.c_name)
  64.             pointers.add_child(node)
  65.             nodes[node.name] = node
  66.  
  67.     return root
  68.  
  69. class DocWriter:
  70.     def __init__(self):
  71.     # parse the defs file
  72.         self.parser = defsparser.DefsParser(())
  73.         self.overrides = override.Overrides()
  74.         self.classmap = {}
  75.         self.docs = {}
  76.  
  77.     def add_sourcedirs(self, source_dirs):
  78.         self.docs = docextract.extract(source_dirs, self.docs)
  79.     def add_tmpldirs(self, tmpl_dirs):
  80.         self.docs = docextract.extract_tmpl(tmpl_dirs, self.docs)
  81.  
  82.     def add_docs(self, defs_file, overrides_file, module_name):
  83.         '''parse information about a given defs file'''
  84.         self.parser.filename = defs_file
  85.         self.parser.startParsing(defs_file)
  86.         if overrides_file:
  87.             self.overrides.handle_file(overrides_file)
  88.  
  89.         for obj in self.parser.objects:
  90.             if not self.classmap.has_key(obj.c_name):
  91.                 self.classmap[obj.c_name] = '%s.%s' % (module_name, obj.name)
  92.         for obj in self.parser.interfaces:
  93.             if not self.classmap.has_key(obj.c_name):
  94.                 self.classmap[obj.c_name] = '%s.%s' % (module_name, obj.name)
  95.         for obj in self.parser.boxes:
  96.             if not self.classmap.has_key(obj.c_name):
  97.                 self.classmap[obj.c_name] = '%s.%s' % (module_name, obj.name)
  98.         for obj in self.parser.pointers:
  99.             if not self.classmap.has_key(obj.c_name):
  100.                 self.classmap[obj.c_name] = '%s.%s' % (module_name, obj.name)
  101.  
  102.     def pyname(self, name):
  103.         return self.classmap.get(name, name)
  104.  
  105.     def __compare(self, obja, objb):
  106.         return cmp(self.pyname(obja.c_name), self.pyname(objb.c_name))
  107.     def output_docs(self, output_prefix):
  108.         files = []
  109.  
  110.         # class hierarchy
  111.         hierarchy = build_object_tree(self.parser)
  112.         filename = self.create_filename('hierarchy', output_prefix)
  113.         fp = open(filename, 'w')
  114.         self.write_full_hierarchy(hierarchy, fp)
  115.         fp.close()
  116.  
  117.     obj_defs = self.parser.objects + self.parser.interfaces + \
  118.                    self.parser.boxes + self.parser.pointers
  119.     obj_defs.sort(self.__compare)
  120.     for obj_def in obj_defs:
  121.             filename = self.create_filename(obj_def.c_name, output_prefix)
  122.         fp = open(filename, 'w')
  123.             if isinstance(obj_def, definitions.ObjectDef):
  124.                 self.output_object_docs(obj_def, fp)
  125.             elif isinstance(obj_def, definitions.InterfaceDef):
  126.                 self.output_interface_docs(obj_def, fp)
  127.             elif isinstance(obj_def, definitions.BoxedDef):
  128.                 self.output_boxed_docs(obj_def, fp)
  129.             elif isinstance(obj_def, definitions.PointerDef):
  130.                 self.output_boxed_docs(obj_def, fp)
  131.         fp.close()
  132.             files.append((os.path.basename(filename), obj_def))
  133.  
  134.         if files:
  135.             filename = self.create_toc_filename(output_prefix)
  136.         fp = open(filename, 'w')
  137.             self.output_toc(files, fp)
  138.             fp.close()
  139.             
  140.     def output_object_docs(self, obj_def, fp=sys.stdout):
  141.     self.write_class_header(obj_def.c_name, fp)
  142.  
  143.         self.write_heading('Synopsis', fp)
  144.         self.write_synopsis(obj_def, fp)
  145.         self.close_section(fp)
  146.  
  147.     # construct the inheritence hierarchy ...
  148.     ancestry = [ (obj_def.c_name, obj_def.implements) ]
  149.         try:
  150.             parent = obj_def.parent
  151.             while parent != None:
  152.                 if parent == 'GObject':
  153.                     ancestry.append(('GObject', []))
  154.                     parent = None
  155.                 else:
  156.                     parent_def = self.parser.find_object(parent)
  157.                     ancestry.append((parent_def.c_name, parent_def.implements))
  158.                     parent = parent_def.parent
  159.         except ValueError:
  160.             pass
  161.         ancestry.reverse()
  162.         self.write_heading('Ancestry', fp)
  163.         self.write_hierarchy(obj_def.c_name, ancestry, fp)
  164.         self.close_section(fp)
  165.  
  166.         constructor = self.parser.find_constructor(obj_def, self.overrides)
  167.         if constructor:
  168.             self.write_heading('Constructor', fp)
  169.             self.write_constructor(constructor,
  170.                                    self.docs.get(constructor.c_name, None),
  171.                                    fp)
  172.             self.close_section(fp)
  173.  
  174.         methods = self.parser.find_methods(obj_def)
  175.         methods = filter(lambda meth, self=self:
  176.                          not self.overrides.is_ignored(meth.c_name), methods)
  177.         if methods:
  178.             self.write_heading('Methods', fp)
  179.             for method in methods:
  180.                 self.write_method(method, self.docs.get(method.c_name, None), fp)
  181.             self.close_section(fp)
  182.  
  183.         self.write_class_footer(obj_def.c_name, fp)
  184.  
  185.     def output_interface_docs(self, int_def, fp=sys.stdout):
  186.     self.write_class_header(int_def.c_name, fp)
  187.  
  188.         self.write_heading('Synopsis', fp)
  189.         self.write_synopsis(int_def, fp)
  190.         self.close_section(fp)
  191.  
  192.         methods = self.parser.find_methods(int_def)
  193.         methods = filter(lambda meth, self=self:
  194.                          not self.overrides.is_ignored(meth.c_name), methods)
  195.         if methods:
  196.             self.write_heading('Methods', fp)
  197.             for method in methods:
  198.                 self.write_method(method, self.docs.get(method.c_name, None), fp)
  199.             self.close_section(fp)
  200.  
  201.         self.write_class_footer(int_def.c_name, fp)
  202.  
  203.     def output_boxed_docs(self, box_def, fp=sys.stdout):
  204.     self.write_class_header(box_def.c_name, fp)
  205.  
  206.         self.write_heading('Synopsis', fp)
  207.         self.write_synopsis(box_def, fp)
  208.         self.close_section(fp)
  209.  
  210.         constructor = self.parser.find_constructor(box_def, self.overrides)
  211.         if constructor:
  212.             self.write_heading('Constructor', fp)
  213.             self.write_constructor(constructor,
  214.                                    self.docs.get(constructor.c_name, None),
  215.                                    fp)
  216.             self.close_section(fp)
  217.  
  218.         methods = self.parser.find_methods(box_def)
  219.         methods = filter(lambda meth, self=self:
  220.                          not self.overrides.is_ignored(meth.c_name), methods)
  221.         if methods:
  222.             self.write_heading('Methods', fp)
  223.             for method in methods:
  224.                 self.write_method(method, self.docs.get(method.c_name, None), fp)
  225.             self.close_section(fp)
  226.  
  227.         self.write_class_footer(box_def.c_name, fp)
  228.  
  229.     def output_toc(self, files, fp=sys.stdout):
  230.         fp.write('TOC\n\n')
  231.         for filename, obj_def in files:
  232.             fp.write(obj_def.c_name + ' - ' + filename + '\n')
  233.  
  234.     # override the following to create a more complex output format
  235.     def create_filename(self, obj_name, output_prefix):
  236.     '''Create output filename for this particular object'''
  237.     return output_prefix + '-' + string.lower(obj_name) + '.txt'
  238.     def create_toc_filename(self, output_prefix):
  239.         return self.create_filename(self, 'docs', output_prefix)
  240.  
  241.     def write_full_hierarchy(self, hierarchy, fp):
  242.         def handle_node(node, fp, indent=''):
  243.             for child in node.subclasses:
  244.                 fp.write(indent + node.name)
  245.                 if node.interfaces:
  246.                     fp.write(' (implements ')
  247.                     fp.write(string.join(node.interfaces, ', '))
  248.                     fp.write(')\n')
  249.                 else:
  250.                     fp.write('\n')
  251.                 handle_node(child, fp, indent + '  ')
  252.         handle_node(hierarchy, fp)
  253.  
  254.     # these need to handle default args ...
  255.     def create_constructor_prototype(self, func_def):
  256.         return func_def.is_constructor_of + '(' + \
  257.                string.join(map(lambda x: x[1], func_def.params), ', ') + \
  258.                ')'
  259.     def create_function_prototype(self, func_def):
  260.         return func_def.name + '(' + \
  261.                string.join(map(lambda x: x[1], func_def.params), ', ') + \
  262.                ')'
  263.     def create_method_prototype(self, meth_def):
  264.         return meth_def.of_object + '.' + \
  265.                meth_def.name + '(' + \
  266.                string.join(map(lambda x: x[1], meth_def.params), ', ') + \
  267.                ')'
  268.  
  269.     def write_class_header(self, obj_name, fp):
  270.     fp.write('Class %s\n' % obj_name)
  271.     fp.write('======%s\n\n' % ('=' * len(obj_name)))
  272.     def write_class_footer(self, obj_name, fp):
  273.         pass
  274.     def write_heading(self, text, fp):
  275.         fp.write('\n' + text + '\n' + ('-' * len(text)) + '\n')
  276.     def close_section(self, fp):
  277.         pass
  278.     def write_synopsis(self, obj_def, fp):
  279.         fp.write('class %s' % obj_def.c_name)
  280.         if isinstance(obj_def, definitions.ObjectDef):
  281.             bases = []
  282.             if obj_def.parent: bases.append(obj_def.parent)
  283.             bases = bases = obj_def.implements
  284.             if bases:
  285.                 fp.write('(%s)' % string.join(bases, ', '))
  286.         fp.write(':\n')
  287.  
  288.         constructor = self.parser.find_constructor(obj_def, self.overrides)
  289.         if constructor:
  290.             prototype = self.create_constructor_prototype(constructor)
  291.             fp.write('    def %s\n' % prototype)
  292.         methods = self.parser.find_methods(obj_def)
  293.         methods = filter(lambda meth, self=self:
  294.                          not self.overrides.is_ignored(meth.c_name), methods)
  295.         for meth in methods:
  296.             prototype = self.create_method_prototype(meth)
  297.             fp.write('    def %s\n' % prototype)
  298.  
  299.     def write_hierarchy(self, obj_name, ancestry, fp):
  300.         indent = ''
  301.         for name, interfaces in ancestry:
  302.             fp.write(indent + '+-- ' + name)
  303.             if interfaces:
  304.                 fp.write(' (implements ')
  305.                 fp.write(string.join(interfaces, ', '))
  306.                 fp.write(')\n')
  307.             else:
  308.                 fp.write('\n')
  309.             indent = indent + '  '
  310.         fp.write('\n')
  311.     def write_constructor(self, func_def, func_doc, fp):
  312.         prototype = self.create_constructor_prototype(func_def)
  313.         fp.write(prototype + '\n\n')
  314.         for type, name, dflt, null in func_def.params:
  315.             if func_doc:
  316.                 descr = func_doc.get_param_description(name)
  317.             else:
  318.                 descr = 'a ' + type
  319.             fp.write('  ' + name + ': ' + descr + '\n')
  320.         if func_def.ret and func_def.ret != 'none':
  321.             if func_doc and func_doc.ret:
  322.                 descr = func_doc.ret
  323.             else:
  324.                 descr = 'a ' + func_def.ret
  325.             fp.write('  Returns: ' + descr + '\n')
  326.         if func_doc and func_doc.description:
  327.             fp.write(func_doc.description)
  328.         fp.write('\n\n\n')
  329.     def write_method(self, meth_def, func_doc, fp):
  330.         prototype = self.create_method_prototype(meth_def)
  331.         fp.write(prototype + '\n\n')
  332.         for type, name, dflt, null in meth_def.params:
  333.             if func_doc:
  334.                 descr = func_doc.get_param_description(name)
  335.             else:
  336.                 descr = 'a ' + type
  337.             fp.write('  ' + name + ': ' + descr + '\n')
  338.         if meth_def.ret and meth_def.ret != 'none':
  339.             if func_doc and func_doc.ret:
  340.                 descr = func_doc.ret
  341.             else:
  342.                 descr = 'a ' + meth_def.ret
  343.             fp.write('  Returns: ' + descr + '\n')
  344.         if func_doc and func_doc.description:
  345.             fp.write('\n')
  346.             fp.write(func_doc.description)
  347.         fp.write('\n\n')
  348.  
  349. class DocbookDocWriter(DocWriter):
  350.     def __init__(self, use_xml=0):
  351.         DocWriter.__init__(self)
  352.         self.use_xml = use_xml
  353.     
  354.     def create_filename(self, obj_name, output_prefix):
  355.     '''Create output filename for this particular object'''
  356.         stem = output_prefix + '-' + string.lower(obj_name)
  357.         if self.use_xml:
  358.             return stem + '.xml'
  359.         else:
  360.             return stem + '.sgml'
  361.     def create_toc_filename(self, output_prefix):
  362.         if self.use_xml:
  363.             return self.create_filename('classes', output_prefix)
  364.         else:
  365.             return self.create_filename('docs', output_prefix)
  366.  
  367.     # make string -> reference translation func
  368.     __transtable = [ '-' ] * 256
  369.     for digit in '0123456789':
  370.         __transtable[ord(digit)] = digit
  371.     for letter in 'abcdefghijklmnopqrstuvwxyz':
  372.         __transtable[ord(letter)] = letter
  373.         __transtable[ord(string.upper(letter))] = letter
  374.     __transtable = string.join(__transtable, '')
  375.  
  376.     def make_class_ref(self, obj_name):
  377.         return 'class-' + string.translate(obj_name, self.__transtable)
  378.     def make_method_ref(self, meth_def):
  379.         return 'method-' + string.translate(meth_def.of_object,
  380.                                             self.__transtable) + \
  381.             '--' + string.translate(meth_def.name, self.__transtable)
  382.  
  383.     __function_pat = re.compile(r'(\w+)\s*\(\)')
  384.     def __format_function(self, match):
  385.         info = self.parser.c_name.get(match.group(1), None)
  386.         if info:
  387.             if isinstance(info, defsparser.FunctionDef):
  388.                 if info.is_constructor_of is not None:
  389.                     # should have a link here
  390.                     return '<function>%s()</function>' % \
  391.                            self.pyname(info.is_constructor_of)
  392.                 else:
  393.                     return '<function>' + info.name + '()</function>'
  394.             if isinstance(info, defsparser.MethodDef):
  395.                 return '<link linkend="' + self.make_method_ref(info) + \
  396.                        '"><function>' + self.pyname(info.of_object) + '.' + \
  397.                        info.name + '()</function></link>'
  398.         # fall through through
  399.         return '<function>' + match.group(1) + '()</function>'
  400.     __parameter_pat = re.compile(r'\@(\w+)')
  401.     def __format_param(self, match):
  402.         return '<parameter>' + match.group(1) + '</parameter>'
  403.     __constant_pat = re.compile(r'\%(-?\w+)')
  404.     def __format_const(self, match):
  405.         return '<literal>' + match.group(1) + '</literal>'
  406.     __symbol_pat = re.compile(r'#([\w-]+)')
  407.     def __format_symbol(self, match):
  408.         info = self.parser.c_name.get(match.group(1), None)
  409.         if info:
  410.             if isinstance(info, defsparser.FunctionDef):
  411.                 if info.is_constructor_of is not None:
  412.                     # should have a link here
  413.                     return '<methodname>' + self.pyname(info.is_constructor_of) + \
  414.                            '</methodname>'
  415.                 else:
  416.                     return '<function>' + info.name + '</function>'
  417.             if isinstance(info, defsparser.MethodDef):
  418.                 return '<link linkend="' + self.make_method_ref(info) + \
  419.                        '"><methodname>' + self.pyname(info.of_object) + '.' + \
  420.                        info.name + '</methodname></link>'
  421.             if isinstance(info, defsparser.ObjectDef) or \
  422.                    isinstance(info, defsparser.InterfaceDef) or \
  423.                    isinstance(info, defsparser.BoxedDef) or \
  424.                    isinstance(info, defsparser.PointerDef):
  425.                 return '<link linkend="' + self.make_class_ref(info.c_name) + \
  426.                        '"><classname>' + self.pyname(info.c_name) + \
  427.                        '</classname></link>'
  428.         # fall through through
  429.         return '<literal>' + match.group(1) + '</literal>'
  430.     
  431.     def reformat_text(self, text, singleline=0):
  432.         # replace special strings ...
  433.         text = self.__function_pat.sub(self.__format_function, text)
  434.         text = self.__parameter_pat.sub(self.__format_param, text)
  435.         text = self.__constant_pat.sub(self.__format_const, text)
  436.         text = self.__symbol_pat.sub(self.__format_symbol, text)
  437.  
  438.         # don't bother with <para> expansion for single line text.
  439.         if singleline: return text
  440.         
  441.         lines = string.split(string.strip(text), '\n')
  442.         for index in range(len(lines)):
  443.             if string.strip(lines[index]) == '':
  444.                 lines[index] = '</para>\n<para>'
  445.                 continue
  446.         lines.insert(0, '<para>')
  447.         lines.append('</para>')
  448.         return string.join(lines, '\n')
  449.  
  450.     # write out hierarchy
  451.     def write_full_hierarchy(self, hierarchy, fp):
  452.         def handle_node(node, fp, indent=''):
  453.             if node.name:
  454.                 fp.write('%s<link linkend="%s">%s</link>' %
  455.                          (indent, self.make_class_ref(node.name),
  456.                           self.pyname(node.name)))
  457.                 if node.interfaces:
  458.                     fp.write(' (implements ')
  459.                     for i in range(len(node.interfaces)):
  460.                         fp.write('<link linkend="%s">%s</link>' %
  461.                                  (self.make_class_ref(node.interfaces[i]),
  462.                                   self.pyname(node.interfaces[i])))
  463.                         if i != len(node.interfaces) - 1:
  464.                             fp.write(', ')
  465.                     fp.write(')\n')
  466.                 else:
  467.                     fp.write('\n')
  468.  
  469.                 indent = indent + '  '
  470.             node.subclasses.sort(lambda a,b:
  471.                                  cmp(self.pyname(a.name), self.pyname(b.name)))
  472.             for child in node.subclasses:
  473.                 handle_node(child, fp, indent)
  474.         if self.use_xml:
  475.             fp.write('<?xml version="1.0" standalone="no"?>\n')
  476.             fp.write('<!DOCTYPE synopsis PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"\n')
  477.             fp.write('    "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">\n')
  478.         fp.write('<synopsis>')
  479.         handle_node(hierarchy, fp)
  480.         fp.write('</synopsis>\n')
  481.  
  482.     # these need to handle default args ...
  483.     def create_constructor_prototype(self, func_def):
  484.         sgml = [ '<constructorsynopsis language="python">\n']
  485.         sgml.append('    <methodname>__init__</methodname>\n')
  486.         for type, name, dflt, null in func_def.params:
  487.             sgml.append('    <methodparam><parameter>')
  488.             sgml.append(name)
  489.             sgml.append('</parameter>')
  490.             if dflt:
  491.                 sgml.append('<initializer>')
  492.                 sgml.append(dflt)
  493.                 sgml.append('</initializer>')
  494.             sgml.append('</methodparam>\n')
  495.         if not func_def.params:
  496.             sgml.append('    <methodparam></methodparam>')
  497.         sgml.append('  </constructorsynopsis>')
  498.         return string.join(sgml, '')
  499.     def create_function_prototype(self, func_def):
  500.         sgml = [ '<funcsynopsis language="python">\n    <funcprototype>\n']
  501.         sgml.append('      <funcdef><function>')
  502.         sgml.append(func_def.name)
  503.         sgml.append('</function></funcdef>\n')
  504.         for type, name, dflt, null in func_def.params:
  505.             sgml.append('      <paramdef><parameter>')
  506.             sgml.append(name)
  507.             sgml.append('</parameter>')
  508.             if dflt:
  509.                 sgml.append('<initializer>')
  510.                 sgml.append(dflt)
  511.                 sgml.append('</initializer>')
  512.             sgml.append('</paramdef>\n')
  513.         if not func_def.params:
  514.             sgml.append('      <paramdef></paramdef')
  515.         sgml.append('    </funcprototype>\n  </funcsynopsis>')
  516.         return string.join(sgml, '')
  517.     def create_method_prototype(self, meth_def, addlink=0):
  518.         sgml = [ '<methodsynopsis language="python">\n']
  519.         sgml.append('    <methodname>')
  520.         if addlink:
  521.             sgml.append('<link linkend="%s">' % self.make_method_ref(meth_def))
  522.         sgml.append(self.pyname(meth_def.name))
  523.         if addlink:
  524.             sgml.append('</link>')
  525.         sgml.append('</methodname>\n')
  526.         for type, name, dflt, null in meth_def.params:
  527.             sgml.append('    <methodparam><parameter>')
  528.             sgml.append(name)
  529.             sgml.append('</parameter>')
  530.             if dflt:
  531.                 sgml.append('<initializer>')
  532.                 sgml.append(dflt)
  533.                 sgml.append('</initializer>')
  534.             sgml.append('</methodparam>\n')
  535.         if not meth_def.params:
  536.             sgml.append('    <methodparam></methodparam>')
  537.         sgml.append('  </methodsynopsis>')
  538.         return string.join(sgml, '')
  539.     
  540.     def write_class_header(self, obj_name, fp):
  541.         if self.use_xml:
  542.             fp.write('<?xml version="1.0" standalone="no"?>\n')
  543.             fp.write('<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"\n')
  544.             fp.write('    "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">\n')
  545.         fp.write('<refentry id="' + self.make_class_ref(obj_name) + '">\n')
  546.         fp.write('  <refmeta>\n')
  547.         fp.write('    <refentrytitle>%s</refentrytitle>\n'
  548.                  % self.pyname(obj_name))
  549.         fp.write('    <manvolnum>3</manvolnum>\n')
  550.         fp.write('    <refmiscinfo>PyGTK Docs</refmiscinfo>\n')
  551.         fp.write('  </refmeta>\n\n')
  552.         fp.write('  <refnamediv>\n')
  553.         fp.write('    <refname>%s</refname><refpurpose></refpurpose>\n'
  554.                  % self.pyname(obj_name))
  555.         fp.write('  </refnamediv>\n\n')
  556.     def write_class_footer(self, obj_name, fp):
  557.         fp.write('</refentry>\n')
  558.     def write_heading(self, text, fp):
  559.         fp.write('  <refsect1>\n')
  560.         fp.write('    <title>' + text + '</title>\n\n')
  561.     def close_section(self, fp):
  562.         fp.write('  </refsect1>\n')
  563.  
  564.     def write_synopsis(self, obj_def, fp):
  565.         fp.write('<classsynopsis language="python">\n')
  566.         fp.write('  <ooclass><classname>%s</classname></ooclass>\n'
  567.                  % self.pyname(obj_def.c_name))
  568.         if isinstance(obj_def, definitions.ObjectDef):
  569.             if obj_def.parent:
  570.                 fp.write('  <ooclass><classname><link linkend="%s">%s'
  571.                          '</link></classname></ooclass>\n'
  572.                          % (self.make_class_ref(obj_def.parent),
  573.                             self.pyname(obj_def.parent)))
  574.             for base in obj_def.implements:
  575.                 fp.write('  <ooclass><classname><link linkend="%s">%s'
  576.                          '</link></classname></ooclass>\n'
  577.                          % (self.make_class_ref(base), self.pyname(base)))
  578.         elif isinstance(obj_def, definitions.InterfaceDef):
  579.             fp.write('  <ooclass><classname>gobject.GInterface'
  580.                      '</classname></ooclass>\n')
  581.         elif isinstance(obj_def, definitions.BoxedDef):
  582.             fp.write('  <ooclass><classname>gobject.GBoxed'
  583.                      '</classname></ooclass>\n')
  584.         elif isinstance(obj_def, definitions.PointerDef):
  585.             fp.write('  <ooclass><classname>gobject.GPointer'
  586.                      '</classname></ooclass>\n')
  587.  
  588.         constructor = self.parser.find_constructor(obj_def, self.overrides)
  589.         if constructor:
  590.             fp.write('%s\n' % self.create_constructor_prototype(constructor))
  591.         methods = self.parser.find_methods(obj_def)
  592.         methods = filter(lambda meth, self=self:
  593.                          not self.overrides.is_ignored(meth.c_name), methods)
  594.         for meth in methods:
  595.             fp.write('%s\n' % self.create_method_prototype(meth, addlink=1))
  596.         fp.write('</classsynopsis>\n\n')
  597.  
  598.     def write_hierarchy(self, obj_name, ancestry, fp):
  599.         fp.write('<synopsis>')
  600.         indent = ''
  601.         for name, interfaces in ancestry:
  602.             fp.write(indent + '+-- <link linkend="' +
  603.                      self.make_class_ref(name) + '">'+ self.pyname(name) + '</link>')
  604.             if interfaces:
  605.                 fp.write(' (implements ')
  606.                 for i in range(len(interfaces)):
  607.                     fp.write('<link linkend="%s">%s</link>' %
  608.                              (self.make_class_ref(interfaces[i]),
  609.                               self.pyname(interfaces[i])))
  610.                     if i != len(interfaces) - 1:
  611.                         fp.write(', ')
  612.                 fp.write(')\n')
  613.             else:
  614.                 fp.write('\n')
  615.             indent = indent + '  '
  616.         fp.write('</synopsis>\n\n')
  617.  
  618.     def write_params(self, params, ret, func_doc, fp):
  619.         if not params and (not ret or ret == 'none'):
  620.             return
  621.         fp.write('  <variablelist>\n')
  622.         for type, name, dflt, null in params:
  623.             if func_doc:
  624.                 descr = string.strip(func_doc.get_param_description(name))
  625.             else:
  626.                 descr = 'a ' + type
  627.             fp.write('    <varlistentry>\n')
  628.             fp.write('      <term><parameter>%s</parameter> :</term>\n' % name)
  629.             fp.write('      <listitem><simpara>%s</simpara></listitem>\n' %
  630.                      self.reformat_text(descr, singleline=1))
  631.             fp.write('    </varlistentry>\n')
  632.         if ret and ret != 'none':
  633.             if func_doc and func_doc.ret:
  634.                 descr = string.strip(func_doc.ret)
  635.             else:
  636.                 descr = 'a ' + ret
  637.             fp.write('    <varlistentry>\n')
  638.             fp.write('      <term><emphasis>Returns</emphasis> :</term>\n')
  639.             fp.write('      <listitem><simpara>%s</simpara></listitem>\n' %
  640.                      self.reformat_text(descr, singleline=1))
  641.             fp.write('    </varlistentry>\n')
  642.         fp.write('  </variablelist>\n')
  643.  
  644.     def write_constructor(self, func_def, func_doc, fp):
  645.         prototype = self.create_constructor_prototype(func_def)
  646.         fp.write('<programlisting>%s</programlisting>\n' % prototype)
  647.         self.write_params(func_def.params, func_def.ret, func_doc, fp)
  648.  
  649.         if func_doc and func_doc.description:
  650.             fp.write(self.reformat_text(func_doc.description))
  651.         fp.write('\n\n\n')
  652.  
  653.     def write_method(self, meth_def, func_doc, fp):
  654.         fp.write('  <refsect2 id="' + self.make_method_ref(meth_def) + '">\n')
  655.         fp.write('    <title>' + self.pyname(meth_def.of_object) + '.' +
  656.                  meth_def.name + '</title>\n\n')
  657.         prototype = self.create_method_prototype(meth_def)
  658.         fp.write('<programlisting>%s</programlisting>\n' % prototype)
  659.         self.write_params(meth_def.params, meth_def.ret, func_doc, fp)
  660.         if func_doc and func_doc.description:
  661.             fp.write(self.reformat_text(func_doc.description))
  662.         fp.write('  </refsect2>\n\n\n')
  663.  
  664.     def output_toc(self, files, fp=sys.stdout):
  665.         if self.use_xml:
  666.             fp.write('<?xml version="1.0" standalone="no"?>\n')
  667.             fp.write('<!DOCTYPE reference PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"\n')
  668.             fp.write('    "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">\n')
  669.             #for filename, obj_def in files:
  670.             #    fp.write('  <!ENTITY ' + string.translate(obj_def.c_name,
  671.             #                                              self.__transtable) +
  672.             #             ' SYSTEM "' + filename + '" >\n')
  673.             #fp.write(']>\n\n')
  674.  
  675.             #fp.write('<reference id="class-reference">\n')
  676.             #fp.write('  <title>Class Documentation</title>\n')
  677.             #for filename, obj_def in files:
  678.             #    fp.write('&' + string.translate(obj_def.c_name,
  679.             #                                    self.__transtable) + ';\n')
  680.             #fp.write('</reference>\n')
  681.             
  682.             fp.write('<reference id="class-reference" xmlns:xi="http://www.w3.org/2001/XInclude">\n')
  683.             fp.write('  <title>Class Reference</title>\n')
  684.             for filename, obj_def in files:
  685.                 fp.write('  <xi:include href="%s"/>\n' % filename)
  686.             fp.write('</reference>\n')
  687.         else:
  688.             fp.write('<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook V4.1.2//EN" [\n')
  689.             for filename, obj_def in files:
  690.                 fp.write('  <!ENTITY ' + string.translate(obj_def.c_name,
  691.                                                           self.__transtable) +
  692.                          ' SYSTEM "' + filename + '" >\n')
  693.             fp.write(']>\n\n')
  694.  
  695.             fp.write('<book id="index">\n\n')
  696.             fp.write('  <bookinfo>\n')
  697.             fp.write('    <title>PyGTK Docs</title>\n')
  698.             fp.write('    <authorgroup>\n')
  699.             fp.write('      <author>\n')
  700.             fp.write('        <firstname>James</firstname>\n')
  701.             fp.write('        <surname>Henstridge</surname>\n')
  702.             fp.write('      </author>\n')
  703.             fp.write('    </authorgroup>\n')
  704.             fp.write('  </bookinfo>\n\n')
  705.  
  706.             fp.write('  <chapter id="class-hierarchy">\n')
  707.             fp.write('    <title>Class Hierarchy</title>\n')
  708.             fp.write('    <para>Not done yet</para>\n')
  709.             fp.write('  </chapter>\n\n')
  710.  
  711.             fp.write('  <reference id="class-reference">\n')
  712.             fp.write('    <title>Class Documentation</title>\n')
  713.             for filename, obj_def in files:
  714.                 fp.write('&' + string.translate(obj_def.c_name,
  715.                                                 self.__transtable) + ';\n')
  716.  
  717.             fp.write('  </reference>\n')
  718.             fp.write('</book>\n')
  719.  
  720. if __name__ == '__main__':
  721.     try:
  722.         opts, args = getopt.getopt(sys.argv[1:], "d:s:o:",
  723.                                    ["defs-file=", "override=", "source-dir=",
  724.                                     "output-prefix="])
  725.     except getopt.error, e:
  726.         sys.stderr.write('docgen.py: %s\n' % e)
  727.     sys.stderr.write(
  728.         'usage: docgen.py -d file.defs [-s /src/dir] [-o output-prefix]\n')
  729.         sys.exit(1)
  730.     defs_file = None
  731.     overrides_file = None
  732.     source_dirs = []
  733.     output_prefix = 'docs'
  734.     for opt, arg in opts:
  735.     if opt in ('-d', '--defs-file'):
  736.         defs_file = arg
  737.         if opt in ('--override',):
  738.             overrides_file = arg
  739.     elif opt in ('-s', '--source-dir'):
  740.         source_dirs.append(arg)
  741.     elif opt in ('-o', '--output-prefix'):
  742.         output_prefix = arg
  743.     if len(args) != 0 or not defs_file:
  744.     sys.stderr.write(
  745.         'usage: docgen.py -d file.defs [-s /src/dir] [-o output-prefix]\n')
  746.         sys.exit(1)
  747.  
  748.     d = DocbookDocWriter()
  749.     d.add_sourcedirs(source_dirs)
  750.     d.add_docs(defs_file, overrides_file, 'gtk')
  751.     d.output_docs(output_prefix)
  752.